/*
EXAMPLE:

#include <iostream>
#include "ThreadPool.h"

int sum(int a, int b) {
    std::cout << "sum" << a << b << std::endl;
    return a+b;
}


int main() {
    std::cout << "hello threadpool." << std::endl;
    ThreadPool pool;
    pool.start();
    std::future<int> result1 = pool.submitTask(sum, 1, 2);
    std::future<int> result2 = pool.submitTask(sum, 3, 4);
    std::cout << result1.get() << std::endl;
    std::cout << result2.get() << std::endl;

    return 0;
}

*/



#ifndef THREAD_POOL_H
#define THREAD_POOL_H


#include <thread>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <queue>
#include <memory>
#include <atomic>
#include <functional>
#include <future>
#include <iostream>





class ThreadPool {
public:
    ThreadPool();
    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(const ThreadPool&) = delete;

    ~ThreadPool();
    

    void setTaskQueMaxThreshold(int Threshold){
        // 设置最大任务数量
        taskQueMaxThreshold_ = Threshold;
    }

    void start(int initThreadNum=std::thread::hardware_concurrency());

    template <typename Func, typename... Args>
    auto submitTask(Func&& func, Args&&... args) -> std::future<decltype(func(args...))>{
        using returnType = decltype(func(args...));
        auto task_ptr = std::make_shared<std::packaged_task<returnType()>>(std::bind(std::forward<Func>(func), std::forward<Args>(args)...)); 
        std::future<returnType> result = task_ptr -> get_future();
        
        std::unique_lock<std::mutex> ulock(taskQueMtx_);
        if (taskNum_ >= taskQueMaxThreshold_) {
            std::cerr << "[Thread Pool] Task queue is full, task submitting failed!" << " queue size: " << taskQue_.size() << 
            ", taskQueMaxThreshold_: " << taskQueMaxThreshold_ <<  std::endl;
            return std::future<returnType>();
        }
        
        taskQue_.emplace(std::make_shared<std::function<void()>>([task_ptr](){
            (*task_ptr)();
        }));
        ++ taskNum_;
        notEmpty_.notify_one();
        return result;
    }
    
    void threadFunc();

private:
    std::vector<std::shared_ptr<std::thread>> threads_; // 线程列表
    size_t initThreadNum_; //初始线程数量
    using Task = std::function<void()>;
    std::queue<std::shared_ptr<Task>> taskQue_; // 任务队列 
    std::atomic_int taskNum_; // 任务数量 
    int taskQueMaxThreshold_; // 最大任务数量

    std::mutex taskQueMtx_; // 任务队列互斥锁
    std::condition_variable notFull_;
    std::condition_variable notEmpty_;

    std::atomic_bool stop_; // 用于关闭线程池

};



#endif